package com.example.kaogong.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.kaogong.common.exception.ParamsErrorException;
import com.example.kaogong.common.utils.Assert;
import com.example.kaogong.common.utils.RespBean;
import com.example.kaogong.sys.mapper.OptionMapper;
import com.example.kaogong.sys.mapper.TeacherMapper;
import com.example.kaogong.sys.mapper.UserMapper;
import com.example.kaogong.sys.pojo.Option;
import com.example.kaogong.sys.pojo.Question;
import com.example.kaogong.sys.mapper.QuestionMapper;
import com.example.kaogong.sys.pojo.Teacher;
import com.example.kaogong.sys.pojo.User;
import com.example.kaogong.sys.pojo.dto.QuestionDto;
import com.example.kaogong.sys.pojo.vo.OptionVo;
import com.example.kaogong.sys.pojo.vo.QuestionVo;
import com.example.kaogong.sys.service.IOptionService;
import com.example.kaogong.sys.service.IQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 题目 服务实现类
 * </p>
 *
 * @author    
 * @since 2022-03-26
 */
@Service
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements IQuestionService {

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private IOptionService optionService;

    @Autowired
    private OptionMapper optionMapper;

    @Autowired
    private TeacherMapper teacherMapper;

    @Autowired
    private UserMapper userMapper;

    /**
     * 教师新增一道试题
     * @param questionDto
     * @param name
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RespBean addQuestion(QuestionDto questionDto, String name) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", name));
        if (user == null || user.getRoleId() != 2)
            return RespBean.error("新增试题失败，权限不足");

        Teacher teacher = teacherMapper.selectOne(new QueryWrapper<Teacher>().eq("uid", user.getUid()).eq("deleted", false));
        if (teacher == null)
            return RespBean.error("新增试题失败， 教师不存在或已被封禁");

        //查询该题目类型和描述是否已存在。只考虑题目描述和题目类型（偷个懒）
        Integer num = questionMapper.selectCount(new QueryWrapper<Question>()
                .eq("question_desc", questionDto.getQuestionDesc())
                .eq("question_type", questionDto.getQuestionType()));
        if (num >= 1)
            return RespBean.error("新增题目失败，该题目已存在题库中");

        // 判断选择题选项是否为空
        if (questionDto.getQuestionType() == 1 || questionDto.getQuestionType() == 2) {
            Assert.notExistNull(questionDto.getOptions(), new ParamsErrorException("选择题选项不能为空"));
        }

        // 插入题目
        Question question = new Question();
        question.setQuestionDesc(questionDto.getQuestionDesc());
        question.setQuestionType(questionDto.getQuestionType());
        question.setTeacherId(teacher.getTeacherId());
        if (questionDto.getAnswer() != null)
            question.setAnswer(questionDto.getAnswer().replaceAll(" ", ""));
        question.setLevel(questionDto.getLevel());
        question.setScore(questionDto.getScore());
        int insertQuestion = questionMapper.insert(question);

        // 判断插入是否成功
        if (insertQuestion < 1) {
            return RespBean.error("新增题目失败");
        }

        // 若为选择题，则插入选择题选项
        if (questionDto.getQuestionType() == 1 || questionDto.getQuestionType() == 2) {
            boolean insertOption = this.insertQuestionOption(questionDto);

            if (!insertOption) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RespBean.error("新增题目失败");
            }
        }
        return RespBean.success();
    }

    /**
     * 根据试题编号删除试题
     * @param questionId
     * @return
     */
    @Override
    public RespBean deleteQuestionByQuestionId(Integer questionId) {
        try {
            int deleteRows = questionMapper.deleteQuestionByQuestionId(questionId);
            if (deleteRows >= 1)
                return RespBean.success();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return RespBean.error();
    }

    /**
     * 分页查询当前教师所出所有试题
     * @param current
     * @param size
     * @param name
     * @return
     */
    @Override
    public RespBean<Page<QuestionVo>> getAllQuestion(Long current, Long size, String name) {
        try {
            User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", name));
            if (user == null || user.getRoleId() != 2)
                return RespBean.error();

            Teacher teacher = teacherMapper.selectOne(new QueryWrapper<Teacher>().eq("uid", user.getUid()));
            if (teacher == null)
                return RespBean.error();

            // 分页查询老师试题
            Page<QuestionVo> questionVoPage = questionMapper.getAllQuestionByTeacherId(new Page<QuestionVo>(current, size), teacher.getTeacherId());

            questionVoPage.getRecords().forEach(questionVo -> {
                if (questionVo.getQuestionType() == 1 || questionVo.getQuestionType() == 2) {
                    List<OptionVo> optionVoList = optionMapper.selectOptionVoListByQuestionId(questionVo.getQuestionId());
                    questionVo.setOptionVoList(optionVoList);
                }
            });
            return RespBean.success(questionVoPage);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return RespBean.error();
    }

    /**
     * 教师修改自己所出试题
     * @param questionVo
     * @param name
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RespBean updateQuestion(QuestionVo questionVo, String name) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", name));
        if (user == null || user.getRoleId() != 2)
            return RespBean.error("权限不足");

        Teacher teacher = teacherMapper.selectOne(new QueryWrapper<Teacher>().eq("uid", user.getUid()));
        Question question = questionMapper.selectOne(new QueryWrapper<Question>().eq("question_id", questionVo.getQuestionId()));
        if (teacher == null || !teacher.getTeacherId().equals(question.getTeacherId()))
            return RespBean.error("权限不足");

        // 修改试题
        boolean updateQuestion = this.updateQuestion(questionVo);
        if (!updateQuestion)
            return RespBean.error();

        // 修改选择题选项
        if (questionVo.getQuestionType() == 1 || questionVo.getQuestionType() == 2) {
            boolean updateOption = this.updateOption(questionVo);
            if (!updateOption) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RespBean.error();
            }
        }
        return RespBean.success();
    }

    /**
     * 获取题库中某种题型的全部试题
     * @param type
     * @return
     */
    @Override
    public RespBean<List<QuestionVo>> getAllQuestionByType(Integer type) {
        List<QuestionVo> questionVoList = questionMapper.getAllQuestionByType(type);
        if (type == 1 || type == 2) {
            questionVoList.forEach(questionVo -> {
                List<OptionVo> optionVoList = optionMapper.selectOptionVoListByQuestionId(questionVo.getQuestionId());
                questionVo.setOptionVoList(optionVoList);
            });
        }
        return RespBean.success(questionVoList);
    }

    private boolean updateOption(QuestionVo questionVo) {
        try {
            for (OptionVo optionVo : questionVo.getOptionVoList()) {
                Option option = new Option();
                option.setOptionName(optionVo.getOptionName());
                option.setOptionValue(optionVo.getOptionValue());

                int update = optionMapper.update(option, new UpdateWrapper<Option>().eq("option_id", optionVo.getOptionId()));
                if (update < 1)
                    return false;
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    private boolean updateQuestion(QuestionVo questionVo) {
        Question question = new Question();
        question.setQuestionDesc(questionVo.getQuestionDesc());
        question.setQuestionType(questionVo.getQuestionType());
        question.setScore(questionVo.getScore());
        question.setLevel(questionVo.getLevel());
        if (questionVo.getAnswer() != null)
            question.setAnswer(questionVo.getAnswer().replaceAll(" ", ""));
        int update = questionMapper.update(question, new UpdateWrapper<Question>().eq("question_id", questionVo.getQuestionId()));
        if (update >= 1)
            return true;
        return false;
    }

    /**
     * 插入选择题选项
     * @param questionDto
     * @return
     */
    private boolean insertQuestionOption(QuestionDto questionDto) {
        Question question = questionMapper.selectOne(new QueryWrapper<Question>()
                .eq("question_desc", questionDto.getQuestionDesc())
                .eq("question_type", questionDto.getQuestionType()));

        List<Option> options = new ArrayList<>();
        questionDto.getOptions().forEach(option -> {
            Option opt = new Option(null, question.getQuestionId(), option.getOptionName(), option.getOptionValue());
            options.add(opt);
        });
        return optionService.saveBatch(options);
    }
}
